package cn.edu.hznu.coursework.controller;

import java.io.File;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import javax.annotation.Resource;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import cn.edu.hznu.coursework.entity.Course;
import cn.edu.hznu.coursework.entity.ResponseResult;
import cn.edu.hznu.coursework.entity.Student;
import cn.edu.hznu.coursework.entity.StudentWork;
import cn.edu.hznu.coursework.entity.TeacherWork;
import cn.edu.hznu.coursework.service.StudentService;
import cn.edu.hznu.coursework.service.TeacherService;

@Controller
@RequestMapping(value = "/student")
public class StudentController {
	
	@Autowired
	private TeacherService teacherService;
	
	@Autowired
	private StudentService studentService;
	
	@Resource
	private ServletContext servletContext;
	
	private static final String STUDENT_FOLDER_PATH = "/upload/student/";
	
	@RequestMapping()
	public String getTeacherPage(HttpSession session, ModelMap model) {
		Student student = (Student) session.getAttribute("user");
		model.addAttribute("userName", student.getName());
		return "student/student.index";
	}
	
	@RequestMapping(value = "/courses", method = RequestMethod.GET)
	@ResponseBody
	public List<Course> getCourseOfStudent(HttpSession session) {
		Student student = (Student) session.getAttribute("user");
		return this.teacherService.findCoursesByStudents(Arrays.asList(student))
				.stream()
				.map(course -> {
					Course info = new Course();
					info.setId(course.getId());
					info.setCourseNo(course.getCourseNo());
					info.setCourseName(course.getCourseName());
					return info;
				}).collect(Collectors.toList());
	}
	
	@RequestMapping(value = "/course/action/add", method = RequestMethod.POST)
	@ResponseBody
	public ResponseResult addCourse(
			@RequestParam(value = "courseName", required = true) String courseName,
			@RequestParam(value = "courseNo", required = true) char courseNo,
			HttpSession session) {
		ResponseResult result = new ResponseResult();
		result.setSucceeded(true);
		Course course = this.teacherService
				.findCourseByCourseNameAndCourseNo(courseName, courseNo);
		Student student = (Student) session.getAttribute("user");
		try {
			if(course == null) {
				throw new Exception("this course does not exist.");
			}
			this.studentService.addCourse(student, course);
		} catch (Exception e) {
			result.setSucceeded(false);
			result.setMessage(e.getMessage());
		}
		return result;
	}
	
	@RequestMapping(value = "/course/id/{id}", method = RequestMethod.DELETE)
	@ResponseBody
	public ResponseResult deleteCourse(@PathVariable Integer id,
			HttpSession session) {
		ResponseResult result = new ResponseResult();
		result.setSucceeded(true);
		Course course = this.teacherService.findCourseById(id);
		Student student = (Student) session.getAttribute("user");
		try {
			this.studentService.removeCourse(student, course);
		} catch (Exception e) {
			result.setSucceeded(false);
			result.setMessage(e.getMessage());
		}
		return result;
	}
	
	@RequestMapping(value = "/teacher-work/id/{id}/student-work", method = RequestMethod.GET)
	@ResponseBody
	public StudentWork getStudentWorkOfTeacherWorkAndStudent(@PathVariable Integer id,
			HttpSession session) {
		TeacherWork teacherWork = this.teacherService.findTeacherWorkById(id);
		Student student = (Student) session.getAttribute("user");
		if(teacherWork != null) {
			StudentWork info = new StudentWork();
			Optional.ofNullable(this.studentService
					.findStudentWorkByStudentAndTeacherWork(student, teacherWork))
					.ifPresent(work -> {
						info.setId(work.getId());
						info.setFilePath(work.getFilePath());
						info.setScore(work.getScore());
						info.setSubmitted(work.isSubmitted());
						info.setSubmitDate(work.getSubmitDate());
					});
			return info;
		} else {
			return null;
		}
	}
	
	@RequestMapping(value = "/student-work/id/{id}", method = RequestMethod.GET)
	@ResponseBody
	public StudentWork getStudentWork(@PathVariable Integer id) {
		StudentWork info = new StudentWork();
			Optional.ofNullable(this.studentService
					.findStudentWorkById(id))
					.ifPresent(work -> {
						info.setId(work.getId());
						info.setFilePath(work.getFilePath());
						info.setScore(work.getScore());
						info.setSubmitted(work.isSubmitted());
						info.setSubmitDate(work.getSubmitDate());
					});
		return info;
	}
	
	@RequestMapping(value = "/student-work/id/{id}/action/submit", method = RequestMethod.POST)
	@ResponseBody
	public ResponseResult addNewTeacherWork(
			@PathVariable Integer id,
			@RequestParam(value = "attachment", required = true) MultipartFile attachment,
			HttpSession session) {

		ResponseResult result = new ResponseResult();
		result.setSucceeded(true);
		Student student = (Student) session.getAttribute("user");
		try {
			StudentWork work = this.studentService.findStudentWorkById(id);
			if (work == null) {
				throw new Exception("The student work does not existed.");
			}
			// Throw exception in advance if any
			StringBuilder courseFolderUrl = new StringBuilder();
			courseFolderUrl.append(STUDENT_FOLDER_PATH);
			courseFolderUrl.append(student.getNo());
			courseFolderUrl.append("/course/");
			courseFolderUrl.append(work.getCourse().getId());
			courseFolderUrl.append("/");
			String studentFolderUrl = servletContext.getRealPath("/WEB-INF"
					+ courseFolderUrl);
			File studentFolder = new File(studentFolderUrl);
			if (!studentFolder.exists()) {
				studentFolder.mkdirs();
			}
			File attachedFile = new File(studentFolder, attachment.getOriginalFilename());
			attachment.transferTo(attachedFile);
			work.setSubmitDate(Calendar.getInstance());
			work.setSubmitted(true);
			work.setFilePath(courseFolderUrl + attachment.getOriginalFilename());
			this.studentService.submitStudentWork(work);
		} catch (Exception e) {
			result.setSucceeded(false);
			result.setMessage(e.getMessage());
		}
		return result;
	}
}
